package com.cgy.utils.base.limiter;

import com.cgy.utils.base.limiter.provider.ILimiterProvider;
import com.google.common.util.concurrent.RateLimiter;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author CH
 */
public class LeakLimiterProvider implements ILimiterProvider {

    /**
     * 漏桶最大限制
     */
    private AtomicInteger maxLimit;
    private RateLimiter rateLimiter;
    private AtomicInteger atomicInteger;

    @Override
    public ILimiterProvider newLimiter(int size) {
        maxLimit = new AtomicInteger(size);
        rateLimiter = RateLimiter.create(size);
        atomicInteger = new AtomicInteger(0);
        return this;
    }

    @Override
    public boolean tryAcquire() {
        if(atomicInteger.intValue() < 0) {
            //throw new IllegalArgumentException("The minimum limit has bean reached");
            return false;
        }
        if(rateLimiter.tryAcquire()) {
            atomicInteger.decrementAndGet();
            return true;
        }
        return false;
    }

    @Override
    public boolean tryAcquire(long time) {
        return tryAcquire(time, TimeUnit.SECONDS);
    }

    @Override
    public boolean tryAcquire(long time, TimeUnit timeUnit) {
        boolean b = tryAcquire();
        if(!b) {
            if(TimeUnit.SECONDS == timeUnit) {
                time = time * 1000;
            } else if(TimeUnit.MINUTES == timeUnit) {
                time = time * 60 * 1000;
            } else if(TimeUnit.HOURS == timeUnit) {
                time = time * 60 * 60* 1000;
            } else if(TimeUnit.DAYS == timeUnit) {
                time = time * 24 * 60 * 60* 1000;
            }
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return tryAcquire();
        }
        return true;
    }

    @Override
    public boolean tryGet() {
        if(atomicInteger.intValue() < maxLimit.intValue()) {
            atomicInteger.incrementAndGet();
            return true;
        } else {
            throw new IllegalArgumentException("The maximum limit has bean reached");
        }
    }
}
